当promise遇到Event Loop

最近一段时间再复习Event loop的时候,遇到promise,以及混合着async/await!!!简直是要了我的小命。正当我一筹莫展之际,有幸读到一篇掘金社区上此类问题的文章:Eventloop不可怕,可怕的是遇上Promise顿时觉得醍醐灌顶。故与诸君分享。

Easy Mode:

​ 来试一下这个开胃菜。

setTimeout(()=>{
   console.log(1) 
},0)
Promise.resolve().then(()=>{
   console.log(2) 
})
console.log(3) 

体会:简单考题。考察eventloop的执行顺序以及宏任务和微任务。输出结果是:[3,2,1]

Normal Mode

​ 第一题是不是不难?那第二题也不难呀!

setTimeout(()=>{
   console.log(1) 
},0)
let a=new Promise((resolve)=>{
    console.log(2)
    resolve()
}).then(()=>{
   console.log(3) 
}).then(()=>{
   console.log(4) 
})
console.log(5) 

体会:考察eventloop和promise.then的执行方式。先上结果:[2,5,3,4,1]。由一点需要注意的是:Promise的链式调用then,每次都会在内部生成一个新的Promise,然后执行then,在执行的过程中不断向微任务(microtask)推入新的函数,因此直至微任务(microtask)的队列清空后才会执行下一波的macrotask。

Hard Mode

I promise。。。。这道题一点都不难

round 1

new Promise((resolve,reject)=>{
    console.log("promise1")
    resolve()
}).then(()=>{
    console.log("then11")
    new Promise((resolve,reject)=>{
        console.log("promise2")
        resolve()
    }).then(()=>{
        console.log("then21")
    }).then(()=>{
        console.log("then23")
    })
}).then(()=>{
    console.log("then12")
})

这个是在第二个例子上的改进。主要体现在再promise.then中又创建了一个promise。MMP 还能不能愉快的玩耍了?你在这玩俄罗斯套娃呢?

吐槽归吐槽,言归正传,遇到这种嵌套的Promise时不要慌(废话,我现在岂止是慌,我慌的一匹。)。首先心中要有一个队列,能够将这些函数放到相应的队列中去问题就迎刃而解了。

第一轮

输出:promise1

micro task queue:[promise1的第一个then]

第二轮

输出:then11,prmoise2

micro task queue:[prmosie2的第一个then,promise1的第二个then]

第三轮

输出:then21,then12

micro task quque:[promise2的第二个then]

第四轮

输出:then 23

round 2

那如果说这边的Promise中then返回一个Promise呢??

new Promise((resolve,reject)=>{
    console.log("promise1")
    resolve()
}).then(()=>{
    console.log("then11")
    return new Promise((resolve,reject)=>{
        console.log("promise2")
        resolve()
    }).then(()=>{
        console.log("then21")
    }).then(()=>{
        console.log("then23")
    })
}).then(()=>{
    console.log("then12")
})

我看你就是在为难我胖虎。这个考的重点是promise返回一个promise的时候,then12相当于是挂载了新的promise的最后一个then的返回值上。所以结果是:[promise1,then11,promise2,then21,then23,then12]

round 3

那要是多来几个promise呢?

new Promise((resolve,reject)=>{
    console.log("promise1")
    resolve()
}).then(()=>{
    console.log("then11")
    new Promise((resolve,reject)=>{
        console.log("promise2")
        resolve()
    }).then(()=>{
        console.log("then21")
    }).then(()=>{
        console.log("then23")
    })
}).then(()=>{
    console.log("then12")
})
new Promise((resolve,reject)=>{
    console.log("promise3")
    resolve()
}).then(()=>{
    console.log("then31")
})

你这是想让我死。哎,有什么办法呢?来吧:

第一轮

输出:promise1,promise3

micro task queue:[promise1的第一个then,promise3的then]

第二轮

输出:then11,promise2,then31

micro task queue:[promise2的第一个then,prmosie1的第一个then]

第三轮

输出:then21,then12

micro task queue:[promise2的第二个then]

第四轮

输出:then 23

Master Mode

你头伸过来,给你看看async/await这个好东西

async function async1() {
    console.log("async1 start");
    await  async2();
    console.log("async1 end");
}

async  function async2() {
    console.log( 'async2');
}

console.log("script start");

setTimeout(function () {
    console.log("settimeout");
},0);

async1();

new Promise(function (resolve) {
    console.log("promise1");
    resolve();
}).then(function () {
    console.log("promise2");
});
console.log('script end'); 

考察在async/await之下,对Eventloop的影响。

async/await仅仅影响的是函数内的执行,而不会影响到函数体外的执行顺序。也就是说async1()并不会阻塞后续程序的执行,**await async2()相当于一个Promise,console.log("async1 end");相当于前方Promise的then之后执行的函数。**

输出结果:[script start,async1 start,async2,promise1,script end,async1 end,promise2,settimeout]

Hell mode

小伙子,不错嘛,前四轮都挺过来了,一看就是个骨骼精奇的人。来来来,尝尝这大碗宽面。不不不,大杂烩。这是我毕生的功力了!

async function async1() {
    console.log("async1 start");
    await  async2();
    console.log("async1 end");
}
async  function async2() {
    console.log( 'async2');
}
console.log("script start");
setTimeout(function () {
    console.log("settimeout");
});
async1()
new Promise(function (resolve) {
    console.log("promise1");
    resolve();
}).then(function () {
    console.log("promise2");
});
setImmediate(()=>{
    console.log("setImmediate")
})
process.nextTick(()=>{
    console.log("process")
})
console.log('script end'); 

F**K。你能不能要点脸。你已经不是想让我死了。你是想让我永世不得超生。

第一轮

输出:[script start,async1 start,async2,promise1,script end]

macro task queue:[setTimeout,setImmediate]

micro task quequ:[process.nextTick,async2的promise.then,Promise.then]

因为nextTick优先级高于promise.then的优先级

第二轮

输出:[process,async1 end,promise2]

macro task quequ:[setTimeout,setImmediate]

micro task queue:[];

第三轮

输出:settimeout

macro task quequ:[setImmediate]

micro task queue:[];

第四轮

输出:setImmediate


  转载请注明: TomoFur 当promise遇到Event Loop

 上一篇
DNS DNS
域名系统(Domain Name System)是互联网使用的命名系统,用来把便于人们使用的机器名字转换为IP地址。 域名服务器根域名服务器根域名服务器是最高层次的域名服务器,也是最重要的域名服务器。所有的根域名服务器都知道所有的顶级域名服
2019-06-21
下一篇 
防抖与节流 防抖与节流
防抖当持续触发事件时,一定时间段内没有再触发时间,时间处理函数才会执行一次,如果设定的时间到来之前,有一次触发了事件,就重新开始延时。 <script> function debounce(fn, wait) {
2019-06-09
  目录